package com.darkidiot.session.redis;

import com.google.common.base.Splitter;
import com.google.common.base.Throwables;
import com.google.common.collect.Sets;
import com.darkidiot.session.conf.Configuration;

import java.util.Set;

import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import redis.clients.jedis.exceptions.JedisException;
import redis.clients.util.Pool;

/**
 * redis连接池封装类
 * session attribute持久化到redis
 * Copyright (c) for darkidiot
 * Date:2017/4/14
 * Author: <a href="darkidiot@icloud.com">darkidiot</a>
 * School: CUIT
 * Desc:
 */
@Slf4j
class JedisPoolExecutor {
    private volatile Pool<Jedis> jedisPool;
    private final static Splitter commaSplitter = Splitter.on(',').trimResults().omitEmptyStrings();

    JedisPoolExecutor(JedisPoolConfig config, boolean sentinel, Configuration configuration) {
        if (sentinel) {
            String sentinelProps = configuration.getSessionRedisSentinelHosts();
            Iterable<String> parts = commaSplitter.split(sentinelProps);
            Set<String> sentinelHosts = Sets.newHashSet(parts);
            String masterName = configuration.getSessionRedisSentinelMasterName();
            jedisPool = new JedisSentinelPool(masterName, sentinelHosts, config);
        } else {
            String redisHost = configuration.getSessionRedisHost();
            int redisPort = configuration.getSessionRedisPort();
            jedisPool = new JedisPool(config, redisHost, redisPort);
        }
    }

    <V> V execute(JedisCallback<V> cb, int index) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.select(index);
            return cb.execute(jedis);
        } catch (JedisException e) {
            log.error("execute jedis command failed, cause by:{}", Throwables.getStackTraceAsString(e));
            throw e;
        }
    }

    void destroy() {
        if (jedisPool != null) {
            jedisPool.destroy();
        }
    }
}
